/*
	Copyright (c) 2011 Andrey O. Zbitnev (azbitnev@gmail.com)
	Licensed under the MIT License (LICENSE).

	$Id: ys.slider.js 30 2012-07-26 12:11:26Z azbitnev@gmail.com $

	version: 0.8pa
*/

(function ($) {

	// private vars
	var serial = 1, controls = { }

	// class slider
	$.ys.slider = {

		set: function (selector, value, raiseEvent) {
			$(selector).each(function () {
				var c = controls[$(this).data('ys-slider-id')]
				if (c) c.setValue(value, raiseEvent)
			})
		},

		get: function (selector) {
			var $sel = $(selector), c = controls[$sel.data('ys-slider-id')]
			if (c) {
				var val = $sel.data('ys-slider-value')
				return (val === undefined ? c.opts.value : val)
			}
			return undefined
		},

		create: function (selector, options) {

			var defaults = {
				min: 0.0,
				max: 1.0,
				value: 0.0,
				orientation: 'horizontal',
				onchange: function (val, $slider) { }
			}

			var opts = $.extend(defaults, options);
			if (opts.min > opts.max) {
				var m = opts.min
				opts.min = opts.max
				opts.max = m
			}
			if (opts.value < opts.min) opts.value = opts.min
			if (opts.value > opts.max) opts.value = opts.max

			var $sel = $(selector)

			if (!$.ys.slider.installed) {
				var savedVal = $.fn.val
				$.fn.val = function (value) {
					var $sel = $(this)
					if ($sel.data('ys-slider-id'))
						return (value === undefined ? $.ys.slider.get($sel) : $.ys.slider.set($sel, value))
					return savedVal.apply(this, arguments)
				}
				$.ys.slider.installed = true
			}

			return $sel.each(function(i, el) {

				var $el = $(el)

				var $sl = $el.children('.thumb:eq(0)')
				var $lln = $el.children('.track:eq(0)')
				var $ln = $el.children('.track-piece:eq(0)')

				if ($sl.length <= 0) {
					$sl = $('<div class="thumb"></div>')
					$el.append($sl)
				}
				if ($lln.length <= 0) {
					$lln = $('<div class="track"></div>')
					$el.append($lln)
				}
				if ($ln.length <= 0) {
					$ln = $('<div class="track-piece"></div>')
					$el.append($ln)
				}

				function shiftHorizontal(dx, raiseEvent) {
					var w = $ln.outerWidth() - $sl.outerWidth()
					var l = parseInt($sl.css('left')) + dx
					if (l < 0) l = 0
					if (l > w) l = w
					$lln.css('width', l.toString() + 'px')
					$sl.css('left', l.toString() + 'px')
					var val = opts.min + (l/w) * (opts.max - opts.min)
					$el.data('ys-slider-value', val)
					if (raiseEvent === undefined || raiseEvent)
						opts.onchange(val, $el)
				}

				function shiftVertical(dy, raiseEvent) {
					var h = $el.height() - $sl.outerHeight()
					var t = parseInt($sl.css('top')) + dy
					if (t < 0) t = 0
					if (t > h) t = h
					$lln.css('height', t.toString() + 'px')
					$sl.css('top', t.toString() + 'px')
					var val = opts.min + (t/h) * (opts.max - opts.min)
					$el.data('ys-slider-value', val)
					if (raiseEvent === undefined || raiseEvent)
						opts.onchange(val, $el)
				}

				var mouse = { x: 0, y: 0, down: false }
				var root = $('html')[0]

				$sl.mousedown(function (evt) {
					mouse.down = true
					mouse.x = evt.clientX
					mouse.y = evt.clientY
					try {
						mouse.sel = root.onselectstart
						root.onselectstart = function () { return false }
					} catch (ex) {
						// msie: do nothing
					}
				})
				$(document).mouseup(function (evt) {
					mouse.down = false
					mouse.x = evt.clientX
					mouse.y = evt.clientY
					try {
						root.onselectstart = mouse.sel
					} catch (ex) {
						// msie: do nothing
					}
				}).mousemove(function (evt) {
					if (mouse.down) {
						var dx = evt.clientX - mouse.x 
						var dy = evt.clientY - mouse.y
						if (opts.orientation == 'horizontal') {
							shiftHorizontal(dx)
						} else {
							shiftVertical(dy)
						}
						mouse.x = evt.clientX
						mouse.y = evt.clientY
					}
				})

				function setValue(value, raiseEvent) {
					if (opts.orientation == 'horizontal') {
						var w = $ln.outerWidth() - $sl.outerWidth()
						var dx = ((value - opts.min) * w) / (opts.max - opts.min)
						$sl.css('left', 0)
						shiftHorizontal(dx, raiseEvent)
					} else {
						var h = $el.height() - $sl.outerHeight()
						var dy = ((value - opts.min) * h) / (opts.max - opts.min)
						$sl.css('top', 0)
						shiftVertical(dy, raiseEvent)
					}
				}

				var id = serial ++
				controls[id] = { 'setValue': setValue, 'opts': opts }
				$el.data('ys-slider-id', id)

				setValue(opts.value)
			})
		}
	}

})(jQuery);

